package com.sc.nft.helper;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.huifu.saturn.cfca.CFCASignature;
import com.huifu.saturn.cfca.SignResult;
import com.huifu.saturn.cfca.VerifyResult;
import com.sc.nft.config.hf.HfConfig;
import com.sc.nft.config.sand.SandConfig;
import com.sc.nft.dao.BankDetailsDao;
import com.sc.nft.dao.HfFastBankDao;
import com.sc.nft.dao.IdcardInfoDao;
import com.sc.nft.dao.UserHfExtDao;
import com.sc.nft.entity.*;
import com.sc.nft.entity.vo.HfFastBankVO;
import com.sc.nft.enums.AccountStatusEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.pool.UserPool;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.util.BankCardUtil;
import com.sc.nft.util.OrderNoUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.Locale;
import java.util.Map;

@Component
@RequiredArgsConstructor
@Slf4j
public class HfPayHelper {

    private final HfFastBankDao hfFastBankDao;
    private final UserHfExtDao userHfExtDao;
    private final IdcardInfoDao idcardInfoDao;




    @Value("${pay.hfConfig.hfOpenSuccess}")
    private String hfOpenSuccess;

    @Value("${pay.wallet.wallet_url}")
    private String walletUrl;

    public JSONObject createOrder(Long orderId,PayOrder payOrder, String productName, String userCustId,String icCard, String userName, String ip, String mac,boolean isSecond) {
        Map<String, Object> params = Maps.newTreeMap();
        params.put("mer_cust_id", HfConfig.merCustId);
        params.put("version", "10");
        if(isSecond){
            params.put("user_cust_id", userCustId);
        }else{
            params.put("user_name", userName);
            params.put("id_card_type", "10");
        }
        params.put("id_card", icCard);
        params.put("order_date", DateTime.now().toString("yyyyMMdd"));
        params.put("order_id", payOrder.getTradeNo());
        params.put("trans_amt", payOrder.getPayAmount().toPlainString());
        params.put("order_expire_time", DateUtil.format(DateUtil.offsetSecond(payOrder.getCloseTime(),-3), "yyyyMMddHHmmss"));
        params.put("bg_ret_url", HfConfig.notifyUrl);
        params.put("ret_url", payOrder.getFrontUrl());

        params.put("goods_desc", productName);
        if(isSecond) {
            params.put("div_type", "1");
        }else{
            params.put("div_type", "0");
            JSONObject divDetail = new JSONObject();
            divDetail.put("divCustId",HfConfig.merCustId);
            divDetail.put("divAcctId",HfConfig.acctId);
            divDetail.put("divAmt",payOrder.getPayAmount().toPlainString());
            divDetail.put("riskDivType","1");
            JSONArray array = new JSONArray();
            array.add(divDetail);
            params.put("div_details", array.toJSONString());
        }

        JSONObject devInfo = new JSONObject();
        devInfo.put("devType", "2");
        devInfo.put("ipAddr", ip);
        devInfo.put("MAC", StrUtil.isNotBlank(mac) ? mac : "020000000000");
        params.put("dev_info_json", devInfo.toJSONString());
        JSONObject objectInfo = new JSONObject();
        if(isSecond){
            objectInfo.put("marketType", 2);
        }else{
            objectInfo.put("marketType", 1);
        }
        params.put("object_info", objectInfo.toJSONString());
        return invoke(payOrder.getUserId(), HfConfig.getPayUrl(), params,Boolean.FALSE);
    }

    /**
     * 退款
     * @param orgTradeNo 原支付订单tradeNo
     * @param tradeNo  退款订单流水号
     * @param orgOrderDate  原订单下单日期
     * @param refundAmount 退款金额
     * @return
     */
    public JSONObject refund(Long refundUserId, String orgTradeNo, String tradeNo, Date orgOrderDate, BigDecimal refundAmount, String ip, String mac) {
        Map<String, Object> params = Maps.newTreeMap();
        params.put("mer_cust_id", HfConfig.merCustId);
        params.put("version", "10");
        params.put("bg_ret_url", HfConfig.mallRefundNotifyUrl);
        params.put("order_date", DateTime.now().toString("yyyyMMdd"));
        params.put("order_id", tradeNo);
        params.put("trans_amt", refundAmount.setScale(2).toPlainString());
        params.put("org_order_date", DateUtil.format(orgOrderDate, "yyyyMMdd"));
        params.put("org_order_id", orgTradeNo);
        JSONObject divDetail = new JSONObject();
        divDetail.put("divCustId",HfConfig.merCustId);
        divDetail.put("divAcctId",HfConfig.acctId);
        divDetail.put("divAmt",refundAmount.setScale(2).toPlainString());
        JSONArray array = new JSONArray();
        array.add(divDetail);
        params.put("div_details", array.toJSONString());
        JSONObject devInfo = new JSONObject();
        devInfo.put("devType", "2");
        devInfo.put("ipAddr", ip);
        devInfo.put("MAC", StrUtil.isNotBlank(mac) ? mac : "020000000000");
        params.put("dev_info_json", devInfo.toJSONString());
        return invoke(refundUserId, HfConfig.getRefundUrl(), params,Boolean.TRUE);
    }

    /**
     * 退货
     * @return
     */
    public JSONObject refund2(Long refundUserId, Date payTime,String orgTradeNo, String tradeNo, Date orgOrderDate, BigDecimal refundAmount, String ip, String mac) {
        Map<String, Object> params = Maps.newTreeMap();
        params.put("mer_cust_id", HfConfig.merCustId);
        params.put("version", "10");
        params.put("bg_ret_url", HfConfig.mallRefundNotifyUrl);
        params.put("order_date", DateUtil.format(payTime,"yyyyMMdd") );
        params.put("order_id", tradeNo);
        params.put("trans_amt", refundAmount.setScale(2).toPlainString());
        params.put("org_order_date", DateUtil.format(orgOrderDate, "yyyyMMdd"));
        params.put("org_order_id", orgTradeNo);
        JSONObject divDetail = new JSONObject();
        divDetail.put("divCustId",HfConfig.merCustId);
        divDetail.put("divAcctId",HfConfig.acctId);
        divDetail.put("divAmt",refundAmount.setScale(2).toPlainString());
        JSONArray array = new JSONArray();
        array.add(divDetail);
        params.put("div_details", array.toJSONString());
        JSONObject devInfo = new JSONObject();
        devInfo.put("devType", "2");
        devInfo.put("ipAddr", ip);
        devInfo.put("MAC", StrUtil.isNotBlank(mac) ? mac : "020000000000");
        params.put("dev_info_json", devInfo.toJSONString());
        return invoke(refundUserId, HfConfig.getRefundUrl2(), params,Boolean.TRUE);
    }


    public JSONObject createMallOrder(Long orderId,MallPayOrderRecord payOrder, String productName, String icCard, String userName, String mac) {
        Map<String, Object> params = Maps.newTreeMap();
        params.put("mer_cust_id", HfConfig.merCustId);
        params.put("version", "10");
        params.put("user_name", userName);
        params.put("id_card_type", "10");
        params.put("id_card", icCard);
        params.put("order_date", DateTime.now().toString("yyyyMMdd"));
        params.put("order_id", payOrder.getTradeNo());
        params.put("trans_amt", payOrder.getPayAmount().toPlainString());
        params.put("order_expire_time", DateUtil.format(payOrder.getCloseTime(), "yyyyMMddHHmmss"));
        params.put("bg_ret_url", HfConfig.mallNotifyUrl);
        params.put("ret_url", payOrder.getFrontUrl());
        params.put("goods_desc", productName);
        params.put("div_type", "0");
        JSONObject divDetail = new JSONObject();
        divDetail.put("divCustId",HfConfig.merCustId);
        divDetail.put("divAcctId",HfConfig.acctId);
        divDetail.put("divAmt",payOrder.getPayAmount().toPlainString());
        divDetail.put("riskDivType","1");
        JSONArray array = new JSONArray();
        array.add(divDetail);
        params.put("div_details", array.toJSONString());
        JSONObject devInfo = new JSONObject();
        devInfo.put("devType", "2");
        devInfo.put("ipAddr", payOrder.getReqIp());
        devInfo.put("MAC", StrUtil.isNotBlank(mac) ? mac : "020000000000");
        params.put("dev_info_json", devInfo.toJSONString());
        JSONObject objectInfo = new JSONObject();
        objectInfo.put("marketType", 1);
        params.put("object_info", objectInfo.toJSONString());
        return invoke(payOrder.getUserId(), HfConfig.getPayUrl(), params,Boolean.FALSE);
    }


    public JSONObject openAccount(UserHfExt userHfExt, String userName, String idCardNo, String mobile,Boolean isWeb) {
        Map<String, Object> params = Maps.newTreeMap();
        params.put("mer_cust_id", HfConfig.merCustId);
        params.put("version", "10");
        params.put("order_date", DateTime.now().toString("yyyyMMdd"));
        params.put("order_id", OrderNoUtil.getOrderNo());
        params.put("user_name", userName);
        params.put("id_card_type", "10");
        params.put("id_card", idCardNo);
        params.put("market_type", 1);
        params.put("acct_usage_type", "wallet");  //买卖钱包户
        params.put("user_id", userHfExt.getHfUserKey());
        if(BooleanUtil.isTrue(isWeb)){
            params.put("ret_url", hfOpenSuccess);
        }else{
            params.put("ret_url", SandConfig.FAST_RETURN_URL);
        }
        params.put("bg_ret_url", HfConfig.accountNotifyUrl);
        return invoke(userHfExt.getUserId(), HfConfig.getWalletUrl(), params,Boolean.FALSE);
    }
    public JSONObject subLedger(String orgOrderId,String orgOrderDate,String amount,String type) {
        Map<String, Object> params = Maps.newTreeMap();
        params.put("mer_cust_id", HfConfig.merCustId);
        params.put("version", "10");
        params.put("order_date", DateTime.now().toString("yyyyMMdd"));
        params.put("order_id", OrderNoUtil.getOrderNo());
        params.put("org_order_id", orgOrderId);
        params.put("org_order_date", orgOrderDate);
        params.put("org_trans_type", type);
        params.put("trans_amt", amount);
        JSONObject divDetail = new JSONObject();
        divDetail.put("divCustId",HfConfig.merCustId);
        divDetail.put("divAcctId",HfConfig.acctId);
        divDetail.put("divAmt",amount);
        divDetail.put("riskDivType","1");
        JSONArray array = new JSONArray();
        array.add(divDetail);
        params.put("div_details", array.toJSONString());
        return invoke(0L, HfConfig.getSubUrl(), params,Boolean.FALSE);

    }

    public JSONObject getWallet(UserHfExt userHfExt,Boolean isWeb) {
        Map<String, Object> params = Maps.newTreeMap();
        params.put("mer_cust_id", HfConfig.merCustId);
        params.put("version", "10");
        params.put("order_date", DateTime.now().toString("yyyyMMdd"));
        params.put("order_id", OrderNoUtil.getOrderNo());
        params.put("user_id", userHfExt.getHfUserKey());
        if(BooleanUtil.isTrue(isWeb)){
            params.put("ret_url", walletUrl);
        }else{
            params.put("ret_url", SandConfig.FAST_RETURN_URL);
        }
        return invoke(userHfExt.getUserId(), HfConfig.getWalletManagerUrl(), params,Boolean.FALSE);
    }

    public JSONObject record(UserHfExt userHfExt, String startTime, String endTime, int pageNo, int pageSize) {
        Map<String, Object> params = Maps.newTreeMap();
        params.put("mer_cust_id", HfConfig.merCustId);
        params.put("version", "10");
        if (ObjectUtil.isNotNull(userHfExt)) {
            params.put("acct_id", userHfExt.getAcctId());
            params.put("user_cust_id", userHfExt.getUserCustId());
        } else {
            params.put("acct_id", HfConfig.acctId);
            params.put("user_cust_id", HfConfig.merCustId);
        }
        params.put("trans_start_date", startTime);
        params.put("trans_end_date", endTime);
        params.put("page_num", pageNo);
        params.put("page_size", pageSize);
        return invoke(userHfExt!=null?userHfExt.getUserId():0L, HfConfig.getQueryUrl(), params,Boolean.FALSE);
    }

    public JSONObject getBalance(UserHfExt userHfExt) {
        Map<String, Object> params = Maps.newTreeMap();
        params.put("mer_cust_id", HfConfig.merCustId);
        params.put("version", "10");
        params.put("acct_id", userHfExt.getAcctId());
        params.put("user_cust_id", userHfExt.getUserCustId());
        return invoke(userHfExt.getUserId(), HfConfig.getBalanceUrl(), params,Boolean.FALSE);
    }


    @Transactional(rollbackFor = Exception.class)
    public HfFastBankVO bindBankCard(Long userId, Long id, String cardNo, String phoneNo) {
        HfFastBank hfFastBank = null;
        UserInfo user = UserPool.getUser();
        if (!user.getIsSm()){
            throw new GlobalRunTimeException(ErrorCode.PLEASE_PERFORM_REAL_NAME_AUTHENTICATION_FIRST);
        }
        IdcardInfo idcardInfo = idcardInfoDao.getByUserIdAndIsPass(userId);
        if (ObjectUtil.isNull(idcardInfo)){
            throw new GlobalRunTimeException("未查询到实名信息");
        }
        if (id != null) {
            hfFastBank = hfFastBankDao.getById(id);
            if (ObjectUtil.isNull(hfFastBank) || hfFastBank.getUserId().longValue() != userId.longValue()) {
                throw new GlobalRunTimeException("未找到银行卡");
            }
        } else {
            HfFastBank hf = hfFastBankDao.getByUserCard(userId, cardNo);
            if (ObjectUtil.isNotNull(hf)) {
                throw new GlobalRunTimeException("该银行卡已绑定");
            }
            hfFastBank = new HfFastBank();
        }
        JSONObject result = bindCardSendSms(userId, idcardInfo.getCardId(), idcardInfo.getName(), cardNo, phoneNo);
//        BankDetails bankDetails = bankDetailsDao.getById(bankId);
        hfFastBank.setUserId(userId);
//        hfFastBank.setBankId(bankId);
        hfFastBank.setBankName(BankCardUtil.getBankNameByCardNo(cardNo));
//        hfFastBank.setBankIcon(bankDetails.getBankIcon());
        hfFastBank.setBankCardNo(cardNo);
        hfFastBank.setName(idcardInfo.getName());
        hfFastBank.setMobile(phoneNo);
        hfFastBank.setStatus(false);
        hfFastBank.setIdentityNo(idcardInfo.getCardId().toUpperCase(Locale.ROOT));
        if (id != null) {
            hfFastBank.updateById();
        } else {
            hfFastBank.insert();
        }
        HfFastBankVO vo = BeanUtil.toBean(hfFastBank, HfFastBankVO.class);
        vo.setOrderId(result.getString("order_id"));
        return vo;
    }

    public JSONObject bindCardSendSms(Long userId, String certificateNo, String name, String cardNo, String phoneNo) {
        Map<String, Object> params = Maps.newTreeMap();
        params.put("mer_cust_id", HfConfig.merCustId);
        params.put("version", "10");
        params.put("order_id", OrderNoUtil.getOrderNo());
        params.put("order_date", DateTime.now().toString("yyyyMMdd"));
        params.put("id_card", certificateNo);
        params.put("user_name", name);
        params.put("card_num", cardNo);
        params.put("card_mobile", phoneNo);
        return invoke(userId, HfConfig.getBindCardSmsUrl(), params,Boolean.FALSE);
    }


    @Transactional(rollbackFor = Exception.class)
    public void bindBankCardConfirm(Long userId, String orderId, String smsCode, Long hfId) {
        HfFastBank hfFastBank = hfFastBankDao.getById(hfId);
        if (ObjectUtil.isNull(hfFastBank) || userId.longValue() != hfFastBank.getUserId().longValue()) {
            throw new GlobalRunTimeException("未找到银行卡");
        }
        Map<String, Object> params = Maps.newTreeMap();
        params.put("mer_cust_id", HfConfig.merCustId);
        params.put("version", "10");
        params.put("order_id", orderId);
        params.put("order_date", DateTime.now().toString("yyyyMMdd"));
        params.put("sms_code", smsCode);
        invoke(userId, HfConfig.getBindCardConfirmUrl(), params,Boolean.FALSE);
        hfFastBank.setStatus(true);
        hfFastBank.updateById();
    }

    private static JSONObject invoke(Long userId, String url, Map<String, Object> params,Boolean isRefund) {
        SignResult signature = CFCASignature.signature(HfConfig.privateKey, HfConfig.privatePwd, JSONObject.toJSONString(params), "UTF-8");
        log.info("汇付请求参数:{}", JSONObject.toJSONString(params));
        String postStr = "version=" + HfConfig.version
                + "&mer_cust_id=" + HfConfig.merCustId
                + "&check_value=" + signature.getSign();
        HttpResponse execute = HttpRequest.post(url).contentType("application/x-www-form-urlencoded").body(postStr).execute();
        JSONObject resultSign = JSONObject.parseObject(execute.body());
        JSONObject result = JSONObject.parseObject(parseCVResult(resultSign.getString("check_value")));
        log.info("汇付返回结果,{}", result);
        SandBizRecord sandBizRecord = new SandBizRecord();
        sandBizRecord.setUserId(userId);
        sandBizRecord.setCustomerOrderNo(MapUtil.getStr(params, "order_id", "000000"));
        sandBizRecord.setBizMethod(url);
        sandBizRecord.setMethodDesc(url);
        sandBizRecord.setReqParams(JSONObject.toJSONString(params));
        sandBizRecord.setResult(JSONObject.toJSONString(result));
        sandBizRecord.insert();
        if (StrUtil.equals(result.getString("resp_code"), "C00000")) {
            return result;
        }else if(isRefund && StrUtil.equals(result.getString("resp_code"), "C00002")){//退款返回值是已受理 C00002
            return result;
        }else {
            throw new GlobalRunTimeException("汇付调用失败:" + result.getString("resp_desc"));
        }
    }


    /**
     * npay 验签
     *
     * @param sign
     * @return
     */
    public static String parseResult(String sign) {
        // 进行验签，参数1为汇付商户号，固定为100001
        VerifyResult verifyResult = CFCASignature.verifyMerSign("100001", sign,
                "utf-8", HfConfig.publicKey);

        System.out.println(verifyResult.toString());
        System.out.println("verifyResult" + verifyResult.toString());

        if ("000".equals(verifyResult.getCode())) {

            // 内容
            String content = new String(verifyResult.getContent(),
                    Charset.forName("utf-8"));
            System.out.println("content = " + content);
            return content;
        } else {
            return "验签失败";
        }
    }

    public static void main(String[] args) {
        System.out.println(parseResult("TUlJSmNnWUpLb1pJaHZjTkFRY0NvSUlKWXpDQ0NWOENBUUV4RHpBTkJnbGdoa2dCWlFNRUFnRUZBRENDQXQ4R0NTcUdTSWIzRFFFSEFhQ0NBdEFFZ2dMTWV5SnlaWE53WDJOdlpHVWlPaUpETURBd01EQWlMQ0p5WlhOd1gyUmxjMk1pT2lMbWlKRGxpcDhpTENKdFpYSmZZM1Z6ZEY5cFpDSTZJalkyTmpZd01EQXhNalkzTVRNeE16WWlMQ0oxYzJWeVgyTjFjM1JmYVdRaU9pSTJOalkyTURBd01UTTBNalV6TVRZeElpd2lkSEpoYm5OZmMzUmhkQ0k2SWxNaUxDSnBibDlqZFhOMFgybGtJam9pSWl3aWFXNWZZV05qZEY5cFpDSTZJaUlzSW1ScGRsOWtaWFJoYVd4eklqb2lXM3RjSW5KcGMydEVhWFpVZVhCbFhDSTZYQ0l4WENJc1hDSmthWFpCYlhSY0lqcGNJakl3T0RrdU5UQmNJaXhjSW1ScGRrRmpZM1JKWkZ3aU9sd2lRVEl3TVRVNU5EQXlYQ0lzWENKa2FYWkRkWE4wU1dSY0lqcGNJalkyTmpZd01EQXhNalkzTVRNeE16WmNJbjFkSWl3aWIzSmtaWEpmYVdRaU9pSmxOelF5TWpRelkySTVOVGMwTURjd1lXSTVZalF4TkdRNFpqTXpZV1poTnlJc0ltOXlaR1Z5WDJSaGRHVWlPaUl5TURJek1EWXhNaUlzSW1KaGJtdGZhV1FpT2lJd01UQTFNREF3TUNJc0luUnlZVzV6WDJGdGRDSTZJakl3T0RrdU5UQWlMQ0ptWldWZlkzVnpkRjlwWkNJNklqWTJOall3TURBeE1qWTNNVE14TXpZaUxDSm1aV1ZmWVdOamRGOXBaQ0k2SWtFeU1ERTFPVFF6TUNJc0ltWmxaVjloYlhRaU9pSXhNaTQxTkNJc0luSmxkRjkxY213aU9pSm9kSFJ3T2k4dmQzZDNMbUpoYVdSMUxtTnZiU0lzSW1KblgzSmxkRjkxY213aU9pSm9kSFJ3Y3pvdkwzZGxZaTFoY0drdVoyOXRaWFJoTG1OdmJTNWpiaTl3WVhsdFpXNTBMMGhtVG05MGFXWjVJaXdpYldWeVgzQnlhWFlpT2lJaUxDSmxlSFJsYm5OcGIyNGlPaUlpTENKd2JHRjBabTl5YlY5elpYRmZhV1FpT2lJeU16QTJNVEl4TWpBeE1ESTNOVEUxTlRVM01DSXNJbTkxZEY5MGNtRnVjMTlwWkNJNklpSXNJbkJoY25SNVgyOXlaR1Z5WDJsa0lqb2lJaXdpY0dGNVgzUjVjR1VpT2lJeE1pSXNJbkpsWVd4ZmRISmhibk5mWVcxMElqb2lJbjJnZ2dUVU1JSUUwRENDQTdpZ0F3SUJBZ0lGUldZUUlwSXdEUVlKS29aSWh2Y05BUUVMQlFBd1dERUxNQWtHQTFVRUJoTUNRMDR4TURBdUJnTlZCQW9NSjBOb2FXNWhJRVpwYm1GdVkybGhiQ0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURVhNQlVHQTFVRUF3d09RMFpEUVNCQlExTWdUME5CTXpFd0hoY05Nakl3T0RFeU1EWXpOekV6V2hjTk1qY3dPREV5TURZek56RXpXakIvTVFzd0NRWURWUVFHRXdKRFRqRVhNQlVHQTFVRUNnd09RMFpEUVNCQlExTWdUME5CTXpFeEVUQVBCZ05WQkFzTUNFeHZZMkZzSUZKQk1Sa3dGd1lEVlFRTERCQlBjbWRoYm1sNllYUnBiMjVoYkMweE1Ta3dKd1lEVlFRRERDQXdOVEZBTVRBd01EQXhRRTQ1TVRNeE1ERXdORFkyTURjek5qUXlOMFZBTVRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTzIwZXBFamFJUjc3cW5QQlhlNHV5dXNXOXlRaDNpbGJYUnZzY2pRcjhOVDYzYk9ZTXMvTkVXYlU2NDhjV3Z6Tm5HWWp0aFlDVWRiWlowSWE4STIxa3N1NFpHSHRodGM4UHVUVHZBMWJjRzFoT09MSlRnc3RNUkVhdzlmZi9VaXpGZFJzU1RiZ0YvbUJIaVZ0UDgzQnI3SnpldWlqNTAwSG5PUGlQZ29tMXFqaVB1RTlKc3RFeDNxR3RZajAvRFFCVU5sdkZYQ1NWeFA2VlNnbjJjV0JRaWVGQ2h6QWxRaktLSE56NXY5R3RwbUZSamlPNVMvMkx1QTd3TlRvTWV0NlRvOVBvSnN4VVVVSjk5RGU4U3o4ZFErZXVOWC9RZ1V4YmdGWUdVanBqWEpyUGV6a0M5OWxHWGpqRXFra1lRcVQyRVdsQUVoV2NZaVpGaFBvTTRLZGgwQ0F3RUFBYU9DQVhnd2dnRjBNR3dHQ0NzR0FRVUZCd0VCQkdBd1hqQW9CZ2dyQmdFRkJRY3dBWVljYUhSMGNEb3ZMMjlqYzNBdVkyWmpZUzVqYjIwdVkyNHZiMk56Y0RBeUJnZ3JCZ0VGQlFjd0FvWW1hSFIwY0RvdkwyTnliQzVqWm1OaExtTnZiUzVqYmk5dlkyRXpNUzl2WTJFek1TNWpaWEl3SHdZRFZSMGpCQmd3Rm9BVTRyUUp5ODFob1hOS2VYL3hpb01MM2JSK2pCMHdEQVlEVlIwVEFRSC9CQUl3QURCSUJnTlZIU0FFUVRBL01EMEdDR0NCSElidktnRUVNREV3THdZSUt3WUJCUVVIQWdFV0kyaDBkSEE2THk5M2QzY3VZMlpqWVM1amIyMHVZMjR2ZFhNdmRYTXRNVFF1YUhSdE1EMEdBMVVkSHdRMk1EUXdNcUF3b0M2R0xHaDBkSEE2THk5amNtd3VZMlpqWVM1amIyMHVZMjR2YjJOaE16RXZVbE5CTDJOeWJETTJPVGt1WTNKc01BNEdBMVVkRHdFQi93UUVBd0lHd0RBZEJnTlZIUTRFRmdRVU9GeXVuWUswUmFyWkpjalZZS3h5NWl2OGxmMHdIUVlEVlIwbEJCWXdGQVlJS3dZQkJRVUhBd0lHQ0NzR0FRVUZCd01FTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFDdi85dlBQdFVoSTc3SjAzVkdnZTdpVGdIZ2pvMS9aSEZncGloV1JvbWJqanZ3Q3FSM0Y0T2ZQSmhXMGNoTU44UFlDUUc5cEtWTXVJL0F0dTJZZjM2L2VwTXF1VVo2QWtJZmlPblc4c3JRL2t6WHd0RE9CVElDWHNmU056VEE4RXVoYWJRa25ST3RxOGxvNkdUT0hZdUpQeTZPMDNGOXNBZG42UUZJSG9FTDBhZ3gwSTBhYlV4ckZiUWpReTJiZE5iSjhrTU56NlJkU25DeXVFS3VIVG0xSFBYck00d2FUTEtMNWhwV1Z5enFneUt6TFhaNEhqNWtLZFY1OFN1SHBjdVBLOFdSVDVjdVB5aStqdlM1c2FzNXFrUlRKcy9PNWlkWGRsZGUwZDNNNzRrUUhFVnlpUG8xNFFmK01EUmp1TlQ1U3MzR3pkYjA0TnV5RXB5VHpRMzNNWUlCakRDQ0FZZ0NBUUV3WVRCWU1Rc3dDUVlEVlFRR0V3SkRUakV3TUM0R0ExVUVDZ3duUTJocGJtRWdSbWx1WVc1amFXRnNJRU5sY25ScFptbGpZWFJwYjI0Z1FYVjBhRzl5YVhSNU1SY3dGUVlEVlFRRERBNURSa05CSUVGRFV5QlBRMEV6TVFJRlJXWVFJcEl3RFFZSllJWklBV1VEQkFJQkJRQXdEUVlKS29aSWh2Y05BUUVCQlFBRWdnRUFXZTNJNHhFNHlGMFZvbC81bWFFRWtyT1lNdjVoMmlWMWJTbkMzQkpTYzBUQnI1cjlxcVZlck1COStIMlVvbFcxMkZNdVhERFNFL1kwcTF3dmRXQ1o0aXEvVDQ0cGRrWUEyZnpzb0t6MFlwUmRZeXlGZDc2Nm0vaUl4ZFpkdWhzWU50eDB3VDJCTmJzdzNHQlU0aFBlQ1FCekYzVE1jb3dsS3NPU3lWR2RnQWdwcVpIaSsyeEdtNVp0cVFhZ0lHK1JPZnFiYzh5YWpYTU1Sa09weSs3d0ZseTR5RTh0RUpqUVlyUmF4OEJCVWc2cmJ4QWQwcW9MQklFSy9FWTRUUDd5QUQ2R20zTDAxOXRBeFUvUmxKQ1FyWEZDZWRWSy8yM2Z3VWs3N0FqMmxyL2dZRWFDbTFDemFWWEFpL2R2T0RoNUVQdm9VeDJVWncxU2tFd0Q2ejc1eFE9PQ===="));
    }

    /**
     * npay 验签
     *
     * @return
     */
    public static String parseCVResult(String checkValue) {

        // 进行验签，参数1为汇付商户号，固定为100001
        VerifyResult verifyResult = CFCASignature.verifyMerSign("100001", checkValue,
                "utf-8", HfConfig.publicKey);
        if ("000".equals(verifyResult.getCode())) {

            // 取得内容
            String content = new String(verifyResult.getContent(),
                    Charset.forName("utf-8"));

            log.info("解签结果：" + content);
            return content;
        } else {
            throw new GlobalRunTimeException("汇付验签失败");
        }
    }

    /**
     * 转账
     */
    public JSONObject transfer(Long userId, BigDecimal amount) {
        UserHfExt userHfExt = userHfExtDao.findByUserId(userId);


        Map<String, Object> params = Maps.newTreeMap();
        params.put("version", "10");
        params.put("mer_cust_id", HfConfig.merCustId);
        params.put("user_cust_id", HfConfig.merCustId);
        params.put("order_id", OrderNoUtil.getOrderNo());
        params.put("order_date", DateTime.now().toString("yyyyMMdd"));
        params.put("div_type", "0");
        params.put("in_cust_id", userHfExt.getUserCustId());
        params.put("in_acct_id", userHfExt.getAcctId());
        params.put("trans_amt", amount.toPlainString());
        return invoke(userId, HfConfig.getTransferUrl(), params,Boolean.FALSE);
    }


    /**
     * 延时分账
     */
    public JSONObject splitMoney(Long userId, PayOrder payOrder,HfTrans hfTrans, HfTransDetail hfTransDetail) {
        UserHfExt userHfExt = userHfExtDao.findByUserId(userId);
        Map<String, Object> params = Maps.newTreeMap();
        params.put("version", "10");
        params.put("mer_cust_id", HfConfig.merCustId);
        params.put("order_id",  OrderNoUtil.getOrderNo());
        params.put("order_date", DateTime.now().toString("yyyyMMdd"));
        params.put("org_order_id",payOrder.getTradeNo() );
        params.put("org_order_date", DateUtil.format(payOrder.getPayTime(),"yyyyMMdd"));
        params.put("org_trans_type", hfTrans.getPayType());
        params.put("trans_amt", hfTransDetail.getAmount().setScale(2).toPlainString());
        JSONObject divDetail = new JSONObject();
        divDetail.put("divCustId",userHfExt.getUserCustId());
        divDetail.put("divAcctId",userHfExt.getAcctId());
        divDetail.put("divAmt",hfTransDetail.getAmount().setScale(2).toPlainString());
        divDetail.put("riskDivType","1");
        JSONArray array = new JSONArray();
        array.add(divDetail);
        params.put("div_details", array.toJSONString());
        return invoke(userId, HfConfig.getSplitUrl(), params,Boolean.FALSE);
    }
}
